import KoaRouter from '@koa/router';

import generateRouter from '@/tools/generateRouter';

import type {
  KoaRoutes,
} from '@/types/koa';

import {
  checkEmailFormat,
  checkAccountFormat,
  checkPasswordIsEmpty,
  checkVerifyCodeFormat,

  validationUserIsExist,
  validationVerifyCodeIsValidity,
  validateVerifyCode,
  validationPasswordIsCorrect,

  validateStateIntercept,
} from '@/middleware/validation.middleware';
import {
  md5,
} from '@/middleware/crypto.middleware';

import {
  emailRegister,
  phoneRegister,

  emailLogin,
  phoneLogin,
  accountLogin,
} from '@/controller/user.controller';
import {
  generateLoginToken,
} from '@/middleware/auth.middleware';

import {
  findUser,
} from '@/service/user.service';
import {
  RedisDB,
} from '@/db/redis.db';

import {
  VERIFY_CODE_OVERDUE_ERROR,
  EMAIL_EXISTING_ERROR,
  EMAIL_NO_EXISTING_ERROR,
  ACCOUNT_NO_EXISTING_ERROR,
} from '@/constant/error/validator.error';

const router = new KoaRouter({
  prefix: '/user',
});

const register: KoaRoutes[] = [
  {
    method: 'post',
    path: '/email/register',
    middleware: [
      checkEmailFormat,
      checkPasswordIsEmpty,
      checkVerifyCodeFormat({ type: 'number' }),

      validationVerifyCodeIsValidity({ redisDB: RedisDB, prefix: 'EMAIL_REGISTER_VERIFY_CODE_', key: 'email' }),
      validateStateIntercept({ state: false, validateKey: 'verifyCodeIsValidity', message: VERIFY_CODE_OVERDUE_ERROR }),
      validationUserIsExist({ service: findUser, key: 'email' }),
      validateStateIntercept({ state: true, validateKey: 'userIsExist', message: EMAIL_EXISTING_ERROR }),

      validateVerifyCode({ redisDB: RedisDB, prefix: 'EMAIL_REGISTER_VERIFY_CODE_', key: 'email' }),
      md5({ key: 'password' }),
    ],
    controller: emailRegister,
  },
  {
    method: 'post',
    path: '/phone/register',
    middleware: [],
    controller: phoneRegister,
  },
];

const login: KoaRoutes[] = [
  {
    method: 'post',
    path: '/email/login',
    middleware: [
      checkEmailFormat,
      checkVerifyCodeFormat({ type: 'string' }),
      checkPasswordIsEmpty,

      validationVerifyCodeIsValidity({ redisDB: RedisDB, prefix: 'GRAPHICS_VERIFY_CODE_', key: 'email' }),
      validateStateIntercept({ state: false, validateKey: 'verifyCodeIsValidity', message: VERIFY_CODE_OVERDUE_ERROR }),
      validationUserIsExist({ service: findUser, key: 'email', cache: true }),
      validateStateIntercept({ state: false, validateKey: 'userIsExist', message: EMAIL_NO_EXISTING_ERROR }),
      validateVerifyCode({ redisDB: RedisDB, prefix: 'GRAPHICS_VERIFY_CODE_', key: 'email' }),
      md5({ key: 'password' }),

      validationPasswordIsCorrect,
      generateLoginToken({ redisDB: RedisDB }),
    ],
    controller: emailLogin,
  },
  {
    method: 'post',
    path: '/phone/login',
    middleware: [],
    controller: phoneLogin,
  },
  {
    method: 'post',
    path: '/account/login',
    middleware: [
      checkAccountFormat,
      checkVerifyCodeFormat({ type: 'string' }),
      checkPasswordIsEmpty,

      validationVerifyCodeIsValidity({ redisDB: RedisDB, prefix: 'GRAPHICS_VERIFY_CODE_', key: 'account' }),
      validateStateIntercept({ state: false, validateKey: 'verifyCodeIsValidity', message: VERIFY_CODE_OVERDUE_ERROR }),
      validationUserIsExist({ service: findUser, key: 'account', cache: true }),
      validateStateIntercept({ state: false, validateKey: 'userIsExist', message: ACCOUNT_NO_EXISTING_ERROR }),
      validateVerifyCode({ redisDB: RedisDB, prefix: 'GRAPHICS_VERIFY_CODE_', key: 'account' }),
      md5({ key: 'password' }),

      validationPasswordIsCorrect,
      generateLoginToken({ redisDB: RedisDB }),
    ],
    controller: accountLogin,
  },
];

const routes = [
  ...register,
  ...login,
];

generateRouter(router, routes);

export default router;
